package com.oromwin.repos.common.helper;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.Arrays;

import com.oromwin.repos.common.Common.CharSet;

public class IOHelper {
    public static final int readShort(byte[] src, int offset) {
        int ch1 = src[offset + 0] & 0xFF;
        int ch2 = src[offset + 1] & 0xFF;
        return ((ch1 << 8) + (ch2 << 0));
    }

    public static final int readInt(byte[] src, int offset) {
        int ch1 = src[offset + 0] & 0xFF;
        int ch2 = src[offset + 1] & 0xFF;
        int ch3 = src[offset + 2] & 0xFF;
        int ch4 = src[offset + 3] & 0xFF;
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }

    public static final long readLong(byte[] src, int offset) {
        int ch1 = src[offset + 0] & 0xFF;
        int ch2 = src[offset + 1] & 0xFF;
        int ch3 = src[offset + 2] & 0xFF;
        int ch4 = src[offset + 3] & 0xFF;
        int ch5 = src[offset + 4] & 0xFF;
        int ch6 = src[offset + 5] & 0xFF;
        int ch7 = src[offset + 6] & 0xFF;
        int ch8 = src[offset + 7] & 0xFF;
        return ((ch1 << 56) + (ch2 << 48) + (ch3 << 40) + (ch4 << 32) + (ch5 << 24) + (ch6 << 16) + (ch7 << 8) + (ch8 << 0));
    }

    public static final int readINT16(byte[] src, int offset) {
        int ch1 = src[offset + 0] & 0xFF;
        int ch2 = src[offset + 1] & 0xFF;
        return ((ch2 << 8) + (ch1 << 0));
    }

    public static final int readINT32(byte[] src, int offset) {
        int ch1 = src[offset + 0] & 0xFF;
        int ch2 = src[offset + 1] & 0xFF;
        int ch3 = src[offset + 2] & 0xFF;
        int ch4 = src[offset + 3] & 0xFF;
        return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
    }

    public static final long readINT64(byte[] src, int offset) {
        int ch1 = src[offset + 0] & 0xFF;
        int ch2 = src[offset + 1] & 0xFF;
        int ch3 = src[offset + 2] & 0xFF;
        int ch4 = src[offset + 3] & 0xFF;
        int ch5 = src[offset + 4] & 0xFF;
        int ch6 = src[offset + 5] & 0xFF;
        int ch7 = src[offset + 6] & 0xFF;
        int ch8 = src[offset + 7] & 0xFF;
        return ((ch8 << 56) + (ch7 << 48) + (ch6 << 40) + (ch5 << 32) + (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
    }

    public static final void writeInt(int src, byte[] dst, int offset) {
        dst[offset + 0] = (byte) ((src & 0xFF000000L) >> 24);
        dst[offset + 1] = (byte) ((src & 0x00FF0000L) >> 16);
        dst[offset + 2] = (byte) ((src & 0x0000FF00L) >> 8);
        dst[offset + 3] = (byte) ((src & 0x000000FFL));
    }

    public static final void writeLong(long src, byte[] dst, int offset) {
        dst[offset + 0] = (byte) ((src & 0xFF00000000000000L) >> 56);
        dst[offset + 1] = (byte) ((src & 0x00FF000000000000L) >> 48);
        dst[offset + 2] = (byte) ((src & 0x0000FF0000000000L) >> 40);
        dst[offset + 3] = (byte) ((src & 0x000000FF00000000L) >> 32);
        dst[offset + 4] = (byte) ((src & 0x00000000FF000000L) >> 24);
        dst[offset + 5] = (byte) ((src & 0x0000000000FF0000L) >> 16);
        dst[offset + 6] = (byte) ((src & 0x000000000000FF00L) >> 8);
        dst[offset + 7] = (byte) (src & 0x00000000000000FFL);
    }

    public static InetAddress getInt2IpAddr(int nIp) throws UnknownHostException {
        byte[] ip = new byte[4];
        ip[0] = (byte) ((nIp & 0xFF000000) >> 24);
        ip[1] = (byte) ((nIp & 0x00FF0000) >> 16);
        ip[2] = (byte) ((nIp & 0x0000FF00) >> 8);
        ip[3] = (byte) (nIp & 0x000000FF);
        return InetAddress.getByAddress(ip);
    }

    public static byte[][] add(byte[][] src, byte[] value) {
        if (src == null)
            src = new byte[0][];
        byte[][] newOne = new byte[src.length + 1][];
        System.arraycopy(src, 0, newOne, 0, src.length);
        newOne[src.length] = value;
        return newOne;
    }

    public static int[] add(int[] src, int value) {
        int[] newOne = new int[src.length + 1];
        System.arraycopy(src, 0, newOne, 0, src.length);
        newOne[src.length] = value;
        return newOne;
    }

    public static long[] add(long[] src, long value) {
        long[] newOne = new long[src.length + 1];
        System.arraycopy(src, 0, newOne, 0, src.length);
        newOne[src.length] = value;
        return newOne;
    }

    public static String[] add(String[] src, String value) {
        String[] newOne = new String[src.length + 1];
        System.arraycopy(src, 0, newOne, 0, src.length);
        newOne[src.length] = value;
        return newOne;
    }

    public static boolean contains(byte[][] src, byte[] value) {
        for (int i = 0; i < src.length; i++) {
            if (Arrays.equals(src[i], value))
                return true;
        }
        return false;
    }

    public static boolean contains(String[] src, String value) {
        if (value == null)
            return false;

        for (int i = 0; i < src.length; i++) {
            if (value.equals(src[i]))
                return true;
        }
        return false;
    }

    public static boolean match(int[] v1, int[] v2) {
        if (v1 == null || v2 == null)
            return false;
        for (int i = 0; i < v1.length; i++) {
            for (int j = 0; j < v2.length; j++) {
                if (v1[i] == v2[j])
                    return true;
            }
        }
        return false;
    }

    private static MessageDigest digester = null;

    public static byte[] md5(String str) throws Exception {
        if (digester == null)
            digester = MessageDigest.getInstance("MD5");
        return digester.digest(str.getBytes("UTF-8"));
    }

    public static byte[] md5(final String... args) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");

            for (String s : args) {
                if (s == null) {
                    s = "";
                }
                md5.update(s.getBytes("UTF-8"));
            }

            return md5.digest();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String byteToHexStr(final byte[] bytes, int offset, int length) {
        StringBuffer buf = new StringBuffer(length * 2);

        for (int i = offset; i < length; ++i) {
            String s = Integer.toHexString(0xFF & bytes[i]).toUpperCase();
            if ((0xFF & bytes[i]) < 0x10) {
                buf.append("0");
            }

            buf.append(s);
        }

        return buf.toString();
    }

    public static double arr2double (byte[] arr, int start) {
        int i = 0;
        int len = 8;
        int cnt = 0;
        byte[] tmp = new byte[len];
        for (i = start; i < (start + len); i++) {
            tmp[cnt] = arr[i];
            //System.out.println(java.lang.Byte.toString(arr[i]) + " " + i);
            cnt++;
        }
        long accum = 0;
        i = 0;
        for ( int shiftBy = 0; shiftBy < 64; shiftBy += 8 ) {
            accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
            i++;
        }
        return Double.longBitsToDouble(accum);
    }

    public static long arr2long (byte[] arr, int start) {
        int i = 0;
        int len = 4;
        int cnt = 0;
        byte[] tmp = new byte[len];
        for (i = start; i < (start + len); i++) {
            tmp[cnt] = arr[i];
            cnt++;
        }
        long accum = 0;
        i = 0;
        for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 ) {
            accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
            i++;
        }
        return accum;
    }
    
    public static void writeUTF8(DataOutputStream dos, String str) throws IOException {
        int len = str.getBytes(CharSet.UTF8).length;
        dos.writeInt(len);
        dos.write(str.getBytes(CharSet.UTF8));
    }

    public static String readUTF8(DataInputStream dis) throws IOException {
        int off = 0;
        int len = dis.readInt();
        byte[] b = new byte[len];
        dis.read(b, off, len);
        String str = new String(b, CharSet.UTF8);
        return str;
    }

    public static final int readCInt(byte[] src, int offset) {
        int ch1 = src[offset + 3] & 0xFF;
        int ch2 = src[offset + 2] & 0xFF;
        int ch3 = src[offset + 1] & 0xFF;
        int ch4 = src[offset + 0] & 0xFF;
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }

    /**
     * @deprecated
     * @param dis
     * @return
     * @throws IOException
     */
    public static String readBytes(DataInputStream dis) throws IOException {
        int off = 0;
        int len = 4;
        byte[] b = new byte[len];
        dis.read(b, off, len);
        int i = readInt(b, off);
        Integer str = new Integer(i);
        return str.toString();
    }
}
